function [fcn_name, input_args, output_args] = fcnparse(file_name);

% FCNPARSE - parse MATLAB M function file header
%
%    [FCN, INPUT, OUTPUT] = FCNPARSE(NAME) reads the MATLAB M file
%    specified by NAME to obtain the function name and arguments as
%    obtained from the function header line.  The function name is
%    returned as FCN, and the input and output arguments are
%    returned as the cell arrays INPUT and OUTPUT.
%
%    The function header is found by searching for the first non-
%    commented line.  If this line begins with 'function', then the
%    line is parsed to obtain the function name and arguments.  If
%    this line does not begin with 'function', then the M file is
%    assumed to be a script, and the function name is set to be
%    '< script >'.  If no non-commented lines are found, the M file
%    is assumed to be a help file, and the function name is set to
%    be '< help >'.

% By:   S.C. Molitor (smolitor@med.unc.edu)
% Date: August 26, 1999

% initialize output to prevent MATLAB errors

fcn_name = '< help >';
input_args = {};
output_args = {};

% check command line arguments

if (nargin ~= 1)
   msgbox('Invalid number of function arguments', 'FCNPARSE Error', 'warn');
   return
elseif (~ischar(file_name))
   msgbox('NAME must be of type CHAR', 'FCNPARSE Error', 'warn');
   return
elseif (exist(file_name) ~= 2)
   msgbox(['Cannot find file ' file_name], 'FCNPARSE Error', 'warn');
   return
end

% open file
% check for errors

fid = fopen(file_name, 'rt');
if (fid == -1)
   msgbox(['Could not open ' file_name], 'FCNMATCH Warning', 'warn');
else
   
   % read lines of file until EOF or function definition encountered
   % account for continuation line ellipsis ('...')
   
   read_flag = 1;
   read_line = '';
   while (read_flag)
      read_line = [read_line fgetl(fid)];
      if (isempty(read_line))
         read_flag = 0;
      elseif (read_line == -1)
         read_flag = 0;
      elseif (~isempty(findstr(read_line, '...')))
         ellipsis_index = findstr(read_line, '...');
         read_line = read_line(1 : ellipsis_index - 1);
      else
         
         % read token from line
         % if token is '%', comment line
         % if token is 'function', parse function header
         % otherwise file must be script
         
         [token, read_line] = strtok(read_line);
         if (isempty(token))
            read_line = '';
         elseif (strcmp(token(1), '%'))
            read_line = '';
         elseif (strcmp(token, 'function'))
            read_flag = 0;
            [fcn_name, input_args, output_args] = parse_header(read_line);
         else
            read_flag = 0;
            fcn_name = '< script >';
         end
      end
   end
   fclose(fid);
end
return

               
function [fcn_name, input_args, output_args] = parse_header(fcn_line);

% PARSE_HEADER - parse MATLAB M function file header line
%
%    [FCN, INPUT, OUTPUT] = PARSE_HEADER(LINE) parses the MATLAB M
%    file function header line provided by LINE.  The function name
%    is returned as FCN, and the input and output arguments are
%    returned as the cell arrays INPUT and OUTPUT.

% By:   S.C. Molitor (smolitor@med.unc.edu)
% Date: August 27, 1999

% initialize output to prevent MATLAB errors

fcn_name = '< script >';
input_args = {};
output_args = {};

% check command line arguments

if (nargin ~= 1)
   msgbox('Invalid number of function arguments', 'PARSE_HEADER Error', 'warn');
   return
elseif (~ischar(fcn_line))
   msgbox('LINE must be of type CHAR', 'PARSE_HEADER Error', 'warn');
   return
end

% strip semicolon from function line

fcn_line = strtok(fcn_line, ';');

% strip function name and arguments from function line
% assume function line is '[x,y,z] = fcn_name(a, b, c)'
% CAUTION:  the output & input arguments are optional!

% strip input arguments

[fcn_line, input_string] = strtok(fcn_line, '(');
input_args = strip_tokens(input_string, ' ,()');

% strip function name
% there may or may not be output arguments left!!

eq_pos = findstr(fcn_line, '=');
if (isempty(eq_pos))
   fcn_name = strtok(fcn_line);
else
   fcn_name = strtok(fcn_line(eq_pos(end) + 1 : end));
   
   % strip output arguments
   
   output_string = fcn_line(1 : eq_pos(end));
   output_args = strip_tokens(output_string, ' ,[]=');
end
return


function token_cell = strip_tokens(token_string, token_delim);

% STRIP_TOKENS - strip tokens from token string
%
%    TOKENS = STRIP_TOKENS(STRING, DELIM) strips tokens from
%    a character array STRING that are separated by the delimiting
%    characters containing in the character string DELIM.  The
%    resulting tokens are stored in the cell array TOKEN.

% By:   S.C. Molitor (smolitor@med.unc.edu)
% Date: August 27, 1999

% initialize output to prevent MATLAB errors

token_cell = {};

% check command line arguments

if (nargin ~= 2)
   msgbox('Invalid number of function arguments', 'STRIP_TOKENS Error', 'warn');
   return
elseif (~ischar(token_string) | ~ischar(token_delim))
   msgbox('Function arguments must be of type CHAR', 'STRIP_TOKENS Error', 'warn');
   return
end

% strip tokens separated by specified delimiters

while (~isempty(token_string))
   [token, token_string] = strtok(token_string, token_delim);
   if (~isempty(token))
      token_cell{end + 1} = token;
   end
end
return
